home *** CD-ROM | disk | FTP | other *** search
Wrap
Text File | 1998-03-19 | 23.1 KB | 592 lines | [ TEXT/MPS ]
# # **************************************************************************** # # File Name: CrashHandling.Lib # # Contains: xxx put contents here xxx # # Written by: KTA # # Copyright: © 1995-1996 by Apple Computer, Inc., all rights reserved. # # **************************************************************************** # C h a n g e H i s t o r y (most recent first): # **************************************************************************** # # Vers Date Author Description # ---- -------- ------ --------------------------------------------- # 1.0.112> 6/18/96 MDF Added global gIsBothMethods to check check for both test case # handling methods. This is a boolean value. # .0.111+> 6/18/96 MDF Changing to correctly handle both test case logging methods. # 1.0.111> 11/15/95 ML InstallEveryTimeMacro() - check $bff to see if macsbug is # installed, replaced Debug with _Debug # .0.110+> 11/14/95 ML InstallEveryTimeMacro - check to see if macsbug is installed and # running # 1.0.110> 5/23/95 ML Merge in changes for Clouseau compatibility # 1.0.19+> 5/23/95 ML # <1.0.19> 5/18/95 ML Don't try gathering w/Applescript if not using Results Express # method # 1.0.18+> 5/17/95 ML # <1.0.18> 5/17/95 ML removed trace() call in GatherTargetCrashLog # 1.0.17+> 5/17/95 ML removed trace() call in GatherTargetCrashLog # <1.0.17> 5/16/95 ML GatherTargetCrashLog()-if crash log exists, rename it first, # using GetRenameCrashLogAs or gapptitle and time to create new # name, concat new name if too long, base success/fail on # renaming. create crash log subfolder based on target name and # date, concat if too long, copy renamed crash log to it. # consolidated printing log onto output window into single set of # calls. DefaultCrashHandler()- Calls global # gConfirmReacquireTarget hook during reacquire phase. # GatherWithAppleScript() - replace gCrashLog with new global # name. # 1.0.16+> 5/12/95 ML various enhancements for Clouseau merge # <1.0.16> 4/25/95 KTA GatherTargetCrashLog() - if we can't verify the crashLogs folder # then we don't continue. # <1.0.15> 3/30/95 KTA GatherTargetCrashLog() - added the Macsbug commands to output. # <1.0.14> 3/30/95 KTA GatherTargetCrashLog() - Removed a call to _FileTool( # "CopyFile"). # <1.0.13> 3/29/95 KTA Deleted _GatherTargetCrashLog(), rolled funtionality into # GatherTargetCrashLog(), added GatherWithAppleScript(). # <1.0.12> 3/28/95 ML _GatherTargetCrashLog() - added a QuitFileTool() call. # <1.0.11> 2/28/95 KTA InstallEveryTimeMacro() - Default pMacroCommands to global # gMacroCommands try block around DebugStr() call, Quit FileTool # if Macsbug is not installed. # <1.0.9> 2/28/95 ML Marked. # <1.0.9> 2/28/95 KTA Able to suspend if target is hung. # <1.0.7> 2/22/95 KTA Added marks # <1.0.6> 2/16/95 KTA InstallEveryTimeMacro() - Check for Macsbug 6.5xx, and insure # macsbug is installed. # <1.0.5> 2/16/95 ML DefaultCrashHandler() - Host will beep if execution suspended, # Call ReacquireTarget with global gMachineName. # ReacquireTarget() - default pTargetName to global gTargetname # <1.0.4> 2/13/95 KTA InstallEveryTimeMacro() - Removed extra Printlns, check version # of Macsbug, Quit Filetool. # <1.0.3> 2/3/95 KTA Added the ability to throw when the crashHandler completes # <1.0.1> 1/31/95 KTA Removed a Trace() call. # # **************************************************************************** Libraries "Results Express.lib","FileToolOperations.lib","TCS.lib","ExceptionHandling.Lib","Output.Lib", "String.Lib", "MemoryMonitorOperations.Lib"; ######################################################################### # GatherTargetCrashLog( pErrorCode, pAbortSuite, pAppleScriptMethod ) #======================================================================== # Author: KTA # Description: 1) Initializes filetool on the target. # 2) checks to see if a file named "CRASHLOG" exists on the root # of boot vol. # 3) Moves a copy of the macsbug data to 'CrashLogs ƒ' on the root. # 4) Reads the file using FileTool # 5) Writes a testcase that includes the data using ResultsExpress. # 6) Deletes the working copy of the file # Note: Step 4 and 5 may be controlled with either AppleScript # or VU. AppleScript is the preferred method as VU has a # 2000 character string limit. If the AppleScript method fails, # we try again using VU. # # Parameters: pErrorCode - The error code that VU recieved when it 1st detected # the crash. # pAbortSuite - a Flag to indicate whether we wish to abort # the current suite because of the crash. # pAppleScriptMethod - a flag used to indicate whether to use # AppleScript or not (for initiating steps 3 and 4 only). # Returns: Nothing # Examples: GatherTargetCrashLog( -1100, 1) # Assumptions: ######################################################################### #======================================================================== # History: # KTA 3/29/95 Created # KTA 3/29/95 Removed a call to _FileTool( "CopyFile") that was left # in accidentally. # KTA 3/29/95 added gMacroCommands # KTA 4/25/95 if we can't verify the crashLogs folder then we don't continue. # ML 5/16/95 if crash log exists, rename it first, using GetRenameCrashLogAs # or gapptitle and time to create new name, concat new name if # too long, base success/fail on renaming. # ML 5/16/95 create crash log subfolder based on target name and date, # concat if too long, copy renamed crash log to it. # ML 5/16/95 consolidated printing log onto output window into single # set of calls # ML 5/18/95 Don't try gathering w/Applescript if not using # Results Express method # MDF 06/18/96 Added global gIsBothMethods to check for both test case # logging methods. ######################################################################### Task GatherTargetCrashLog( pErrorCode, pAbortSuite := 1, pAppleScriptMethod := 1 ) begin global gTestCaseLoggingMethod, kTCSResultsExpressMethod, gIsBothMethods; tSuccessFlag := false; successWithApplescript := false; theData := 0; filetoolInit := _FileTool( "initialize", {1},true); if(filetoolInit[1] = 0) begin doesExist := _FileTool( "FileExists", {global gCrashLog},true); if(doesExist[1] = 0) begin newCrashLogName := GetRenameCrashLogAs(); if not newCrashLogName begin if not (global gapptitle) newCrashLogName := "unknown"; else newCrashLogName := gapptitle; end; try match [time m:?month d:?day h:?Tm]; catch theErr ExceptionDispatcher(theErr); newCrashLogName := ConcatNameString(newCrashLogName, " {Tm}", 31); RenamedFile := _FileTool( "Rename", {global gCrashLog,0,newCrashLogName},true); if (RenamedFile[1] = 0) begin tSuccessFlag := true; # Success logstr("Renamed the Macsbug log file '{gCrashLog}' to '{newCrashLogName}'",1,'RStatus'); ## Copy the Macsbug datafile into a folder for posterity and work ## with a disposable copy of it if (ExistsOrCreate("{global gBootVol}:CrashLogs ƒ:")) begin newCrashLogSubFolder := ConcatNameString(global gMachineName, " {month}/{day}", 31); ExistsOrCreate ("{global gBootVol}:CrashLogs ƒ:{newCrashLogSubFolder}:"); ## Move a copy of the file into the 'CrashLogs ƒ' folder theCopy := _FileTool( "CopyFile",{"{global gBootVol}:{newCrashLogName}", 0, "{global gBootVol}:CrashLogs ƒ:{newCrashLogSubFolder}:{newCrashLogName}"} ); if (theCopy[1] = 0) begin LogStr("The crash log file named '{newCrashLogName}' has been copied to the folder '{gBootVol}:CrashLogs ƒ: {newCrashLogSubFolder}'",1,'RStatus'); global gfullPathCrashLogName := "{global gBootVol}:{newCrashLogName}"; ## Use AppleScript to read the file and write the testcase ## Note: We try to use applescript, if it fails for any reason ## we try again using VU (vu is limited to the 1st 2000 chars). if(pAppleScriptMethod) begin pTCSpecifier := {2,"Crash Handler","Compatibility","SPEC S&L", "CRASH occurred on target - AppleScript", -3}; if ((gTestCaseLoggingMethod = kTCSResultsExpressMethod) or gIsBothMethods) begin if(GatherWithAppleScript( pErrorCode , pTCSpecifier)) successWithApplescript := true; else println "NOTE: Problem gathering with AppleScript. Will attempt to gather 1st 2000 chars of Macsbug data using VU instead."; end; else println("Can't gather log using Applescript method because your test case tracking method isn't set to 'Results Express'."); end; # if(pAppleScriptMethod) ## Use VU to read the file (note: only first 2000 chars) theDataList := _FileTool('Read',{gfullPathCrashLogName,0,2000,0}, true); DeleteTheFile(gfullPathCrashLogName); QuitFileTool(); # need to quit here because we clean # abort out of TCSEnd if(theDataList[1] = 0) theData := theDataList[2]; else println "Couldn't READ bytes ",theDataList[1], theDataList[3] ; LogStr("••••••••• ERROR:CRASH occurred on target •••••••• The commands that were issued in Macsbug are '{global gMacroCommands}'."); if (successWithApplescript) begin logstr("Gathered Macsbug log using AppleScript "); if (theData) begin logstr("The following output is the first 2000 chars:" ); println "∂n", theData; end; end; ## Abort the suite if desired if(successWithApplescript and pAbortSuite) CleanAbort('CRASH occurred on target', pAbortSuite); if not(pAppleScriptMethod) or (pAppleScriptMethod and not successWithApplescript) begin TCSStart({ 1, "Crash Handler" },"CRASH occurred on target",,0); # Start TCS (but don't match the target) TCSEnd({ 1, "Crash Handler" }, -3,,pErrorCode,"{theData}", global gMachineName,pAbortSuite); end; end; # if (theCopy[1] = 0) else begin println "Error Copying file "; Println "Error : ", theCopy[1], " , ", theCopy[3]; end; end; # ExistsOrCreate("{global gBootVol}:CrashLogs ƒ:") else println "Error while checking for '{global gBootVol}:CrashLogs ƒ:' folder"; end; # RenamedFile[1] = 0 else begin println "Problem renaming file '{gCrashLog}' to '{newCrashLogName}'"; Println "Error : ", RenamedFile[1], " , ", RenamedFile[3]; end; end; # if(doesExist[1] = 0) else begin println "File '{gCrashLog}' does not exist"; Println "Error : ", doesExist[1], " , ", doesExist[3]; end; end; else begin println "Error initializing FileTool"; Println "Error : ", filetoolInit[1], " , ", filetoolInit[3]; end; QuitFileTool(); return(tSuccessFlag); end; ######################################################################### # GatherWithAppleScript( pErrorCode, pTCSpecifier ) #======================================================================== # Author: KTA # Description: Steps 4 and 5 of GatherTargetCrashLog() using AppleScript # 1) … # 2) … # 3) … # 4) Reads the file using FileTool # 5) Writes a testcase that includes the data using ResultsExpress. # # Parameters: pErrorCode - The error code that VU recieved when it 1st detected # the crash. # pTCSpecifier - The data used to identify the testcase if the form: # {Number,"Set","Type","Owner","Description", Result} # Returns: true - succesful # false - an error occured # Examples: GatherWithAppleScript( -1100 , {2,"Set","Type","Owner","Description", -3}); # # Assumptions: ######################################################################### #======================================================================== # History: # KTA 3/39/95 Created # ML 5/16/95 replace gCrashLog with gfullPathCrashLogName ######################################################################### task GatherWithAppleScript( pErrorCode, pTCSpecifier) begin #println "pErrorCode - ", pErrorCode; #println "global gCurSuiteID - ", global gCurSuiteID; #println "global gCrashLog - ", global gCrashLog; #println "gMachineName - ", global gMachineName; theScript := 'on DoGather( pErrorCode, pParentSuite, pCrashLogPath, pMachineName, pTCID ) try beep tell application "FileTool" of machine "' + "{global gMachineName}" + '" try set CrashLogData to DoService "Read" Parameters {pCrashLogPath, 0, 32000, 0} beep on error errMsg number ErrCode display dialog ("Read failed " & ErrCode as string) & " : " & errMsg error {ErrCode, errMsg} end try end tell set kTestCaseRecord to 4 try tell application "Results Express" set x to DoService "NewRecord" Parameters ¬ {kTestCaseRecord, pParentSuite, ¬ { {"TCNo", Item 1 of pTCID}, ¬ {"TCSet", Item 2 of pTCID}, ¬ {"TCType", Item 3 of pTCID}, ¬ {"TCOwner", Item 4 of pTCID}, ¬ { "TCDesc", Item 5 of pTCID},¬ { "Result", Item 6 of pTCID},¬ { "NumericVal", pErrorCode }, ¬ { "Comments", pMachineName },¬ {"TextVal", CrashLogData} ¬ } ¬ } beep end tell on error errMsg number ErrCode display dialog ("NewRecord failed " & ErrCode as string) & " : " & errMsg error {ErrCode, errMsg} end try beep return true on error errMsg number ErrCode return false end try end DoGather("' + "{pErrorCode}" + '", "' + "{global gCurSuiteID}" + '", "' + global gfullPathCrashLogName + '", "' + global gMachineName + '", ' + "{pTCSpecifier}" + ' )'; # End AppleScript string #Println "Length of AppleScript - ",Card(theScript); #Println "AppleScript - '", theScript,"'"; x := AppleScriptString( theScript ); #Println "This is the call to AppleScriptString() - ", x; if(x[1] = 0) return (true); else begin Println "!@#$% Problem trying to run AppleScript to gather Macsbug Data"; Println "Error : ", x[1], " , ", x[3]; return(false); end; end; ######################################################################### # DefaultCrashHandler(pParamList) #======================================================================== # Description: simple Crash handler prototype # Parameters: pParamList: list of parameters # element 1 := What to do about the suite(1 - Fail the suite/0 don't fail the suite) # element 2 := What to do if can't aquire target (1 - abort script/0-suspend) # element 3 := What to do if can't gather crashlog (1 - abort script/0-turn off crashHandler but continue) # element 4 := [optional] Throw when done or not - will throw whatever it is defined as # Returns: result of error handler TASK call, or throw if fatal # Examples: DefaultCrashHandler({1}) # Assumptions: VU 2.1 #======================================================================== # History: # ML 2/16/95 Host will beep if execution suspended # Call ReacquireTarget with global gMachineName # ML 5/12/95 added hook for additional testing to confirm reacquire # KTA 5/17/95 Added support for AIQ logging ######################################################################### TASK DefaultCrashHandler(pErrID, pParamList := {1,1,1}) begin LogStr("DefaultCrashHandler() - error is {pErrID} : {pParamList}", 4, 'RStatus'); # call with support for AIQ logging println "global gMachineName", global gMachineName; ## LOG SOME INFO if not(_matchBoolean([target t:global gMachineName]!)) begin LogStr("DefaultCrashHandler() - Target failure (error = {pErrID})", 4, 'RError'); # call with support for AIQ logging LogStr("DefaultCrashHandler() - Target '{global gMachineName}' CRASHED! WAITING FOR RESTART TO CONTINUE SCRIPT…", 1, 'RStatus'); # call with support for AIQ logging end; else if(pErrID = -1096) # Target Restarted begin LogStr("DefaultCrashHandler() - Target failure (error = {pErrID})", 4, 'RError'); # call with support for AIQ logging LogStr("DefaultCrashHandler() - Target '{global gMachineName}' RESTARTED UNEXPECTEDLY!", 1, 'RStatus'); # call with support for AIQ logging end; else begin LogStr("DefaultCrashHandler() - Target failure (error = {pErrID})", 4, 'RError'); # call with support for AIQ logging LogStr("DefaultCrashHandler() - Target '{global gMachineName}' FAILED AND THEN RECOVERED", 1, 'RStatus'); # call with support for AIQ logging end; if not(ReacquireTarget(global gMachineName)) begin if not(pParamList[2]) # Pause until user resets target begin pParamList[1] := 0; LogStr("DefaultCrashHandler() - Please reset the Target",1, 'RStatus'); while not(ReacquireTarget(global gMachineName)) # Wait forever sysbeep(); end; else begin LogStr("DefaultCrashHandler() - Target crashed and we can't reaquire it",1,'RStatus');; TCSStart({ 2, "Crash Handler" },"CRASH occurred on target",,0); # Start TCS (but don't match the target) TCSEnd({ 2, "Crash Handler" }, -3,"Cannot reaquire target - aborting suite",,,global gMachineName,-2); return; end; end; ## This is the hook to do a second restart if global gConfirmReacquireTargetHook call (gConfirmReacquireTargetHook); ## Determine if you want to abort the suite if there was a crash if(pParamList[1]) AbortSuite := -2; # Abort the suite else AbortSuite := ''; ## Gather the Crash log and put it into a TCS if not(GatherTargetCrashLog(pErrID, AbortSuite)) begin if(pParamList[3]) AbortSuite := -2; # Abort the suite else AbortSuite := ''; LogStr("Target crashed and we couldn't gather the Macsbug Log",1,'RStatus'); TCSStart({ 3, "Crash Handler" },"CRASH occurred on target",,0); TCSEnd({ 3, "Crash Handler" }, -3,"Cannot gather the Macsbug Log",,,global gMachineName,AbortSuite); if(AbortSuite = -2) return; end; ## Clear stack, and reinstall macro if you didn't want to abort the suite if (AbortSuite <> -2) # Only if pParamList[1] = 0 (Don't abort suite if crash) begin ClearStack(); InstallEveryTimeMacro(); # Send the Debug string used by crash handler end; ## If if not(isUndefined(pParamList[4])) # Will allow us to exit old style quicklook scripts Throw pParamList[4]; end; ######################################################################### # ReacquireTarget() #======================================================================== # Author: KTA # Description: # Parameters: None # Returns: Nothing # Examples: # Assumptions: ######################################################################### #======================================================================== # History: # ML 2/16/95 default pTargetName to global gMachineName ######################################################################### Task ReacquireTarget(pTargetName := global gMachineName, pZoneName := "*") begin returnVal := 0; origTimeOut := CommandTimeOut(400); # Set this too a large value in case it takes awhile to reboot or if 'Shutdown warning' is present. result := acquireTarget(pTargetName, pZoneName); if ((result = 0) or (result = 2)) # Reaquired target successfully begin # Need to wait till all inits get loaded. while not _matchBoolean([menu]) wait(10); LogStr("Reaquired target successfully",4); returnVal := 1; end; CommandTimeOut(origTimeOut); return(returnVal); end; ######################################################################### # InstallEveryTimeMacro() #======================================================================== # Description: Sends a Debug sting that invokes the everytime macro and # restarts the target if there was a crash. # Parameters: pMacroCommands - commands to be included in the everytime # macro which will execute when the target crashes. # Returns: nothing # Examples: InstallEveryTimeMacro('HOW; WH; TD; HT; SC;'); # Assumptions: VU 2.1 #======================================================================== # History: # KTA 2/13/95 Removed extra Printlns, check version of Macsbug, Quit Filetool. # KTA 2/16/95 Check for Macsbug 6.5xx, and insure macsbug is installed. # KTA 2/28/95 default pMacroCommands to global gMacroCommands # try block around DebugStr() call. # ML 11/14/95 check $bff to see if macsbug is installed, replaced # Debug with _Debug ######################################################################### Task InstallEveryTimeMacro(pMacroCommands := global gMacroCommands) begin if not(global gCrashLog) begin global gBootVol := NameOfBootVolume(); global gCrashLog := "{gBootVol}:CRASHLOG"; end; tSysFolder := PathToSpecialFolder('macs'); correctMacsBugVersion := false; macsbugInstalled := false; if(DoesFileExist("{tSysFolder}Macsbug")) begin tMacsbugVers := _FileTool('ReadVersion',{"{tSysFolder}Macsbug", 1})[2][1]; QuitFileTool(); if(StrToNum(tMacsbugVers[1]) >= 6) begin if (StrToNum(tMacsbugVers[3]) >= 5) begin correctMacsBugVersion := true; MemoryMonitorInit(); if (_MemoryMonitor('ReadBytes',{ {0, 3071}, 4 })[2][1]) # first byte at $bff is non-zero if macsbug is installed # $bff in decimal is 3071 begin LogStr( "Installing EveryTime macro - SET scrollprompt off;MC everytime 'LOG ∂"{gCrashLog}∂";{pMacroCommands}; RB;LOG'; g"); _DebugStr( "SET scrollprompt off;MC everytime 'LOG ∂"{gCrashLog}∂";{pMacroCommands}; RB;LOG'; g", true ); macsbugInstalled := true; end; # if (_MemoryMonitor('ReadBytes',{ {0, 3071}, 4 })[1]) else LogStr("!@#$% - MacsBug is not active"); MemoryMonitorQuit(); end; end; if not (correctMacsBugVersion) LogStr("!@#$% - Installing our Everytime macro requires MacsBug v6.5d8 or greater, you are using v{tMacsbugVers}"); end; else begin LogStr("!@#$% - MacsBug is not in the system folder"); QuitFileTool(); end; if not (correctMacsBugVersion) or not (macsbugInstalled) begin LogStr("!@#$% - Turning our crashHandling mechanism - OFF"); global gCrashHandling := 0; end; end; ######################################################################### # GetRenameCrashLogAs() #======================================================================== # Author: ML # Description: Accesser for getting the name that the crash log will # be renamed as. # Parameters: none # Returns: gRenameCrashLogAs # Examples: GetRenameCrashLogAs(); # Assumptions: None #======================================================================== # History: # 5/16/95 ML created ######################################################################### TASK GetRenameCrashLogAs() begin return global gRenameCrashLogAs; end; ######################################################################### # SetRenameCrashLogAs(pName) #======================================================================== # Author: ML # Description: Accesser for setting the name that the crash log will # be renamed as. # Parameters: none # Returns: none # Examples: SetRenameCrashLogAs("my custom log name") # Assumptions: None #======================================================================== # History: # 5/16/95 ML created ######################################################################### TASK SetRenameCrashLogAs(pName) begin global gRenameCrashLogAs := pName; end;